<?PHP
namespace SDF\Lib\Account;

use MongoDB\BSON\UTCDateTime;
use SDF\Common\Auth;
use SDF\Common\Cache;
use SDF\Common\Cookie;
use SDF\Common\Utils;
use SDF\Core\Controllers;
use SDF\Lib\Log\log;

/**
 * 后台权限验证公共控制器类
 * @package SDF\Lib\Account
 */
class AuthConsole extends Controllers {
    protected static $admin_user;
    protected static $domain_name = 'nbyyy.com';
    protected static $admin_token_cookie_name = 'admin_token';//管理员账户cookie token名。
    protected static $username_arr = array('yj','admin','gjb');//超级管理员列表
    /**
     * 授权构造
     * auth_console constructor.
     */
    public function __construct() {
        self::$domain_name = DOMAIN_NAME;
        $admin_user = self::getAdminUserByCookie();
        $oauth_callback = $_SERVER['REQUEST_SCHEME'].'://'.@$_SERVER['HTTP_HOST'] . @$_SERVER['REQUEST_URI'];//受访地址,用于给登录成功后回跳
        if (empty($admin_user)) {
            if (IS_AJAX) {//如果是ajax，返回状态码，否则重定向到登陆页。
                self::form_json(array(), '登录已超时！', 301);exit;
            } else {
                header("Refresh:0;url=http://admin." . self::$domain_name . "/?oauth_callback=" . $oauth_callback);exit;
            }
        }
        $admin_user_model = new admin_user();
        self::$admin_user = (array)$admin_user_model->findOneByUsername($admin_user['username']);
        if (empty(self::$admin_user)){
            if (IS_AJAX) {//如果是ajax，返回状态码，否则重定向到登陆页。
                self::form_json(array(), '登录已超时！', 301);exit;
            }else{
                header("Refresh:0;url=http://admin." . self::$domain_name . "/?oauth_callback=" . $oauth_callback);exit;
            }
        }
        $this->_write_log(self::$admin_user);//写入操作日志
        if (self::$admin_user['status'] != 1) {
            $this->_error('账户状态异常，请联系管理员处理。');exit;
        }
        if (!in_array(self::$admin_user['username'], self::$username_arr)) {//超级管理员不需要权限校验
            if (empty(self::$admin_user['sys_authority'])) {//如果没有系统权限,直接拒绝访问。
                if(IS_AJAX){
                    self::form_json(array(),'没有系统权限',300);exit;
                }else{
                    $this->_error('没有系统权限');
                }
            } else {
                $http_host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];
                //系统权限校验
                if(!self::checkAuthSys($http_host,self::$admin_user['sys_authority'])){
                    $this->_error('需要系统授权，请联系管理员授权');exit;
                }
                //todo 特殊权限校验
                if(!self::checkAuthSpecial($http_host)){//特殊权限
                    $this->_error('需要特殊权限，请联系管理员授权');exit;
                }
            }
            //$host = str_replace('.'.self::$domain_name,'',$_SERVER['HTTP_HOST']);
        }
        $this->DATA['admin_user'] = self::$admin_user;
    }

    /**
     * 获取系统列表（暂时写死，后期考虑读配置文件或者读数据库）
     * @param array $admin_user 管理员账户信息
     * @return array
     */
    public static function getSysAuthorityList($admin_user = []) {
        if(empty($admin_user['username'])){
            return [];
        }
        $sys_authority = \SysAuthority::SYS_AUTHORITY;//暂时把权限列表写死到配置文件中。后期改成读数据库的。
        if(in_array($admin_user['username'],self::$username_arr)){//超级管理员直接返回所有系统菜单
            return $sys_authority ;//测试的时候直接返回所有系统
        }
        if(empty($admin_user['sys_authorit'])){
            return array();
        }
        $user_sys_authority_arr = $admin_user['sys_authorit'];
        $sys_authority_arr = [];//实际权限列表
        foreach ($user_sys_authority_arr as $authority_code){
            $authority_code = strtoupper($authority_code);
            if (isset($sys_authority[$authority_code])){
                $sys_authority_arr[] = $sys_authority[$authority_code];
            }
        }
        return $sys_authority_arr;
    }

    /**
     * 写后台操作日志日志
     * @param $member_info
     * @return bool|\MongoDB\Driver\WriteResult
     */
    private function _write_log($member_info){
        if(isset($GLOBALS['PARSE_INFO']['action']) and $GLOBALS['PARSE_INFO']['action'] == 'get_order_count'){//获取订单数量的请求不需要写日志
            return false;
        }
        $ip = Utils::GetIP();
        $url = $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
        $admin_action_log_model = new log('admin_action_log');
        $user_operation_log = array();
        $user_operation_log['user_id'] = $member_info['_id'] . '';
        $user_operation_log['username'] = $member_info['username'];
        $user_operation_log['nickname'] = @$member_info['nickname'];
        $user_operation_log['controller'] = $GLOBALS['PARSE_INFO']['control'];
        $user_operation_log['method'] = $GLOBALS['PARSE_INFO']['action'];
        $user_operation_log['request'] = $_REQUEST;
        $user_operation_log['ip_address'] = $ip;
        $user_operation_log['url'] = $url;
        $user_operation_log['Ymd'] = date('Ymd');
        $user_operation_log['create_time'] = new UTCDateTime();
        return $admin_action_log_model->insertOne($user_operation_log);
    }

    /**
     * 检测特殊权限
     * @param $host
     * @return bool
     * @throws \Exception
     */
    private static function checkAuthSpecial($host) {
        $host = trim($host);
        $cache_model = new Cache();
        $key = 'SPECIAL_AUTH_'.md5($host);
        $special_auth_json = $cache_model->get($key);//取得当前访问系统的所有特殊权限列表。
        //var_dump($special_auth_json);exit;
        if(empty($special_auth_json)){
            $auth_special_model = new auth_special();//特殊权限类
            $special_auth_arr = $auth_special_model->listByHost($host);//获取当前系统需要特殊权限验证的列表
            $cache_model->set($key,json_encode($special_auth_arr),600);//缓存10分钟
        }else{
            $special_auth_arr = json_decode($special_auth_json);
        }
        foreach($special_auth_arr as $special_auth){//todo 需要对所有特殊权限进行匹配，比较消耗资源，后面需要优化算法。
            if(fnmatch($special_auth->auth_code,$_SERVER['REQUEST_URI'])  ){
                if(in_array(self::$admin_user['username'],$special_auth->auth_owner)){
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 检测系统权限
     * @param string $host 受访域名
     * @param array $admin_user_sys_authority_arr 被授予的系统权限列表
     * @return bool
     */
    private static function checkAuthSys($host,$admin_user_sys_authority_arr){
        foreach ($admin_user_sys_authority_arr as $code){
            if(fnmatch($code.'.'.DOMAIN_NAME,$host)){
                return true;
            }
        }
        return false;
    }

    /**
     * 设置登陆成功的token
     * @param $_id
     * @param $username
     * @param $nickname
     * @return string
     * @throws \Exception
     */
    public static function setloginSucceedCookie($_id,$username,$nickname){
        $token = Auth::user_encode($_id.'',$username,$nickname);
        Cookie::set_cookie(self::$admin_token_cookie_name, $token, strtotime(date('Y-m-d') . ' +7 day') + 14400 ,'/',DOMAIN_NAME);//第二天4点过期
        return $token;
    }

    /**
     * 通过Cookie获取用户身份
     * @return array
     * @throws \Exception
     */
    public static function getAdminUserByCookie(){
	    /*$admin_user['id'] = '59f3e3905d0694015a02fd02';
	    $admin_user['username'] = 'AnoU8IRPR4aiP35dCiiKqLcAiEiE';
	    $admin_user['nickname'] = '袁吉';
	    $admin_user['encode_time'] = time()+3600;
	    return $admin_user;*/
        $token = Cookie::get_cookie(self::$admin_token_cookie_name);
        if(empty($token)){
            return [];
        }
        $admin_user = Auth::user_decode($token);//解析token，获取用户信息
        return $admin_user;
        /*$admin_user_model = new admin_user();
        self::$admin_user = $admin_user_model->findOneById($admin_user['_id']);*/
    }

    /**
     * 删除用户登陆token
     */
    public static function delAdminUserCookie(){
        Cookie::delete_cookie(self::$admin_token_cookie_name,DOMAIN_NAME,'/');
    }

}